#pragma once

#include <list>
#include <map>
#include <hash_map>
#include <iostream>
#include <string>
#include <sstream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <cmath>


using boost::property_tree::ptree;
using boost::property_tree::write_xml;
using boost::property_tree::xml_writer_settings;

using namespace std;
using namespace stdext;

class ActionNode
{
private:
	ActionNode * _parent;
	list<string> _observations;
	hash_map<string, ActionNode*> _childNodes;
	string _nodeName;

	string _state;
	int _occurrences;

public:	
	ActionNode(string nodeName, list<string> observations, string state);
	ActionNode(string nodeName, ActionNode* parent, list<string> observations);
	void ActionNode::SetChildNodes(hash_map<string, ActionNode*> childNodes);
	bool ActionNode::AddChildNode(string observation, ActionNode* node);
	int ActionNode::GetChildTreeLength();
	string ActionNode::GetNodeName();
	int ActionNode::GetNodeLevel();
	string ActionNode::ToString();
	string ActionNode::ToStringOccurrences();
	string ActionNode::ToTikzString(string observation, string side, int level);

	//Methods for comparing and merging trees
	hash_map<string, ActionNode*> ActionNode::GetChildNodes();
	list<string> ActionNode::GetObservations();
	void ActionNode::SetParent(ActionNode * parent);
	ActionNode * ActionNode::GetParent();

	string ActionNode::GetState();
	void ActionNode::IncrementOccurrences();

	ptree ActionNode::ToXml();

	int ActionNode::GetOcurances();

	void ActionNode::CalculateOcurances();

	bool ActionNode::IsCompatible(ActionNode * actionNode, double epsilon);
	bool ActionNode::Hoeffding(ActionNode * actionNode, double epsilon);
	int ActionNode::GetTotalChildCount();
	bool ActionNode::IsCompleteNode();

	list<ActionNode*> ActionNode::ToListOfNodes();
	void ActionNode::MergeMissingChildrenFromNode(ActionNode * actionNode);

	string ActionNode::GetObservationForActionNode(ActionNode * searchNode);

	list<string> ActionNode::GetObservationsMissingActions();
	bool ActionNode::ContainsMissingActionsForObservations(list<string> observations);

	bool ActionNode::CloneMerge(ActionNode * mergeWithNode);

	bool ActionNode::IsCompatibleWithNode(ActionNode * testNode);

	bool ActionNode::MergeWithNode(ActionNode * testNode);
};

